<script type='text/javascript'>

var gSmileRand = {
	_mod : 2048,
	_seed : (new Date()).getTime(),
	resetSeed : function(in_seed) {
		this._seed = in_seed;
	},
	rand : function() {
		this._seed = Math.abs((17 * this._seed - 1) % this._mod);
		return this._seed / this._mod;
	},
};

var gSmile = {
	seed : -1,
	level : -1,
	cells : [],
	firstTry : true,
	canOpen : -1,
	init : function(in_w, in_h, in_level, in_seed) {
		this.level = in_level;
		this.seed = in_seed;
		this.canOpen = in_w * in_h;
		gSmileRand.resetSeed(in_seed);
		for (var i = 0; i < in_h; i++) {
			this.cells[i] = [];
			for (var j = 0; j < in_w; j++) {
				if (Math.floor(gSmileRand.rand() * 10) < in_level) {
					this.canOpen--;
					this.cells[i][j] = {
						open : false,
						bomb : true,
						risk : -1,
						own : null
					};
				} else {
					this.cells[i][j] = {
						open : false,
						bomb : false,
						risk : -1,
						own : null,
					};
				}
			}
		}
		for (var i = 0; i < in_h; i++) {
			for (var j = 0; j < in_w; j++) {
				this.cells[i][j].risk = this.checkRisk(j, i);
			}
		}
	},
	inMap : function(in_x, in_y) {
		if ((in_y < 0) || (this.cells.length <= in_y)) {
			return false;
		}
		if ((in_x < 0) || (this.cells[in_y].length <= in_x)) {
			return false;
		}
		return true;
	},
	arrounds : function(in_x, in_y) {
		var ret = [];
		var x = Number(in_x);
		var y = Number(in_y);
		var candidate = [
			[x - 1, y - 1],
			[x + 0, y - 1],
			[x + 1, y - 1],
			[x - 1, y + 0],
			[x + 1, y + 0],
			[x - 1, y + 1],
			[x + 0, y + 1],
			[x + 1, y + 1]
		];
		for (var i = 0; i < candidate.length; i++) {
			if (this.inMap(candidate[i][0], candidate[i][1])) {
				ret.push(candidate[i]);
			}
		}
		return ret;
	},
	checkRisk : function(in_x, in_y) {
		var risk = 0;
		var targets = this.arrounds(in_x, in_y);
		for (var i = 0; i < targets.length; i++) {
			if (this.cells[targets[i][1]][targets[i][0]].bomb) {
				risk++;
			}
		}
		return risk;
	},
	isFinished : function() {
		return (this.canOpen == 0);
	},
	safeOpen : function(in_player, in_x, in_y) {
		var opened = [];
		var cell = this.cells[in_y][in_x];
		if (!cell.open) {
			cell.open = true;
			cell.own = in_player;
			if (cell.risk == 0) {
				var targets = this.arrounds(in_x, in_y);
				for (var i = 0; i < targets.length; i++) {
					opened = opened.concat(this.safeOpen(in_player, targets[i][0], targets[i][1]));
				}
			}
			opened.push({x : in_x, y : in_y, r : cell.risk});
			this.canOpen--;
		}
		return opened;
	},
	allOpen : function() {
		var opened = [];
		for (var y = 0; y < this.cells.length; y++) {
			for (var x = 0; x < this.cells[y].length; x++) {
				var cell = this.cells[y][x];
				if (!cell.open) {
					cell.open = true;
					opened.push({x : x, y : y, r : cell.risk, b : cell.bomb});
					this.canOpen--;
				}
			}
		}
		return opened;
	},
	open : function(in_player, in_x, in_y) {
		var cell = this.cells[in_y][in_x];
		if (this.firstTry) {
			if (cell.bomb) {
				cell.bomb = false;
				var targets = this.arrounds(in_x, in_y);
				for (var i = 0; i < targets.length; i++) {
					this.cells[targets[i][1]][targets[i][0]].risk--;
				}
				this.canOpen++;
			}
			this.firstTry = false;
		}
		if (cell.bomb) {
			/* alert('game over'); */
			return null;
		} else {
			return this.safeOpen(in_player, in_x, in_y);
		}
	},
	riversi : function(in_player, in_x, in_y) {
		var reversed = [];
		var targets = this.arrounds(in_x, in_y);
		for (var i = 0; i < targets.length; i++) {
			var x = targets[i][0];
			var y = targets[i][1];
			var v = {
				dx : x - in_x,
				dy : y - in_y,
				op : false,
				cl : false,
				pool : []
			};
			do {
				var cell = this.cells[y][x];
				if (!cell.own) {
					break;
				}
				if (cell.own == in_player) {
					if (v.op) {
						v.cl = true;
					}
					break;
				} else {
					v.op = true;
				}
				v.pool.push({x : x, y : y, r : cell.risk});
				x += v.dx;
				y += v.dy;
			} while (this.inMap(x, y));
			if (v.cl) {
				reversed = reversed.concat(v.pool);
			}
		}
		for (var i = 0; i < reversed.length; i++) {
			this.cells[reversed[i].y][reversed[i].x].own = in_player;
		}
		return reversed;
	}
};

</script>
<div id='field'></div>
<script type='text/javascript' src='ConnJS.php'></script>
<script>

function dp(in_txt)
{
	if (console && console.log) {
		console.log(in_txt);
	}
}

HTMLTableElement.prototype.td = function(in_x, in_y)
{
	return this.rows[in_y].cells[in_x];
};

HTMLTableElement.prototype.createCells = function(in_x, in_y, in_callback)
{
	for (var y = 0; y < in_y; y++) {
		var tr = document.createElement('TR');
		for (var x = 0; x < in_x; x++) {
			var td = document.createElement('TD');
			if (in_callback) {
				(in_callback)(td, x, y);
			}
			tr.appendChild(td);
		}
		this.appendChild(tr);
	}
};

Sample2pUI = {
	_cnt : 0,
	_player : null,
	_players : ['red', 'blue'],
	_table : null,
	_order : function() {
		return this._players[this._cnt % this._players.length];
	},
	start : function(in_level, in_seed, in_first) {
		gSmile.init(this._table.rows[0].cells.length, this._table.rows.length, in_level, in_seed);
		this._player = this._players[(in_first ? 0 : 1)];
		var tds = this._table.getElementsByTagName('TD');
		for (var i = 0; i < tds.length; i++) {
			tds.item(i).className = 'unknown';
		}
	},
	isStarted : function() {
		return this._player ? true : false;
	},
	next : function() {
		this._cnt++;
	},
	setupTable : function(in_x, in_y, in_elem) {
		this._table = document.createElement('TABLE');
		in_elem.appendChild(this._table);
		this._table.createCells(in_x, in_y, (function(self) {
			return function(in_td, in_x, in_y) {
				in_td.className = 'default';
				in_td.onclick = function() {
					var pos = {x : in_x, y : in_y};
					if (self._player == self._order()) {
						if (self.openCell(pos)) {
							self.next();
							p2p.sendAppData(pos);
						}
					} else {
						dp('wait!');
					}
				}
			}
		})(this));
	},
	openCell : function(in_pos) {
		if (gSmile.isFinished()) {
			return false;
		}
		var opened = gSmile.open(this._order(), in_pos.x, in_pos.y);
		if (!opened) {
			var opened = gSmile.allOpen();
			while (cell = opened.pop()) {
				var td = this._table.td(cell.x, cell.y);
				if (cell.b) {
					td.className = 'bomb';
					td.innerHTML = '*';
				} else {
					td.innerHTML = cell.r;
				}
			}
			// location.reload();
			return false;
		}
		if (opened.length == 0) {
			return false;
		}
		opened = opened.concat(gSmile.riversi(this._order(), in_pos.x, in_pos.y));
		var totalms = 500;
		var timeout = Math.ceil(totalms / opened.length);
		var delay = (function(self) {
			var order = self._order();
			return function() {
				if (opened.length == 0) {
					if (gSmile.isFinished()) {
						var score = {};
						for (i = 0; i < self._table.rows.length; i++) {
							for (j = 0; j < self._table.rows[i].cells.length; j++) {
								var cls = self._table.td(j, i).className;
								if (typeof(score[cls]) == 'undefined') {
									score[cls] = 1;
								} else {
									score[cls]++;
								}
							}
						}
						alert('finished');
						for (var cls in score) {
							if (cls == 'unknown') {
								continue;
							}
							alert(cls + ' : ' + score[cls]);
						}
					}
					return;
				}
				var pos = opened.pop();
				with (self._table.td(pos.x, pos.y)) {
					innerHTML = pos.r;
					className = order;
				}
				window.setTimeout(delay, timeout);
			};
		})(this);
		(delay)();
		return true;
	}
};

var LEVEL = 2;

Sample2pUI.setupTable(10, 5, document.getElementById('field'));

function appStarted(in_started, in_wait_time)
{
	if (in_started) {
		if (in_wait_time > 0) {
			dp('1st-player');
			var rand = Math.floor(Math.random() * 1000);
			p2p.sendAppData(rand);
			Sample2pUI.start(LEVEL, rand, true);
		} else {
			dp('2nd-player');
		}
	} else {
		dp('error (appStarted)');
	}
}

function recvAppData(in_data)
{
	if (in_data) {
		if (Sample2pUI.isStarted()) {
			if (Sample2pUI.openCell(in_data)) {
				Sample2pUI.next();
			}
		} else {
			Sample2pUI.start(LEVEL, in_data, false);
		}
	} else {
		dp('ignore null');
	}
}

function lostConnection()
{
	dp('error (lostConnection)');
}

p2p.start('smile2-client', appStarted, recvAppData, lostConnection);

</script>
<style type='text/css'>

TD {
	width : 20px;
	height : 23px;
	padding: 0px;
	border-style: solid;
	border-width: 1px;
	border-radius : 3px;
	color: #ffffff;
	text-align: center;
	text-shadow: -1px 0px 2px #666666, 0px -1px 2px #666666, 0px 1px 2px #666666, 0px 1px 2px #666666; 
}
TD.default {
	border-color: #999999 #666666 #666666 #999999;
	background-color: #cccccc;
}
TD.unknown {
	border-color: #999999 #666666 #666666 #999999;
	background: -moz-linear-gradient(bottom, #999999, #ffffff);
	background: -webkit-gradient(linear, right bottom, left top, from(#999999), to(#ffffff));
}
TD.red {
	border-color: #cc6666 #993333 #993333 #cc6666;
	background: -moz-linear-gradient(bottom, #cc6666, #ffcccc);
	background: -webkit-gradient(linear, right bottom, left top, from(#cc6666), to(#ffcccc));
}
TD.blue {
	border-color: #6666cc #333399 #333399 #6666cc;
	background: -moz-linear-gradient(bottom, #6666cc, #ccccff);
	background: -webkit-gradient(linear, right bottom, left top, from(#6666cc), to(#ccccff));
}
TD.bomb {
	border-color: #999999 #666666 #666666 #999999;
	background: -moz-linear-gradient(bottom, #999999, #666666);
	background: -webkit-gradient(linear, right bottom, left top, from(#999999), to(#666666));
}

</style>
